﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Web;
using FDFtpSync.Core;
using FDFtpSync.Entities;
using FDFtpSync.Entities.Extensions;
using FDFtpSync.Utils;

namespace FDFtpSync.Client
{
    /*
     * CreatedOn: 2018-05-23
     * CreatedBy: Jackie Lee(天宇遊龍)
     */
    /// <summary>
    /// Http下载器
    /// </summary>
    public class HttpFileSyncServer : BaseSyncServer, IFileSyncServer
    {
        public HttpFileSyncServer(ILogger logger) : base(logger)
        {
        }

        protected override void Run()
        {
            _isRunning = true;
            _lastRunTime = DateTime.Now;
            TryDo(() =>
            {
                Info("开始进入同步...");
                var clientConfig = SyncContext.Current.GetSyncConfig<ClientSyncConfig>();
                _lastRunTime = DateTime.Now;
                var client = new HttpClient();
                foreach (var clientPath in clientConfig.ClientPaths)
                {
                    var content = new StringContent(new { Password = clientConfig.ServerConnectPassword, PathName = clientPath.ServerName }.ToJson());
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    var res = client.PostAsync(clientConfig.FileListUrl, content).Result.Content.ReadAsStringAsync().Result;
                    var apiRes = res.FromJson<ApiResult<List<TransFile>>>();
                    if (apiRes.Code == 0)
                    {
                        foreach (var transFile in apiRes.Result)
                        {
                            var saveFileName = $"{clientPath.Path}{transFile.Path}";
                            if (transFile.Type == PathType.Dir)
                            {
                                PathHelper.CheckDir(saveFileName);
                            }
                            else
                            {
                                PathHelper.CheckDir(Path.GetDirectoryName(saveFileName));
                                if (!PathHelper.HasChanged(transFile, saveFileName))
                                {
                                    continue;
                                }
                                bool bSuccess;
                                do
                                {
                                    bSuccess = ThreadPool.QueueUserWorkItem(Download,
                                        new { transFile, clientPath.ServerName, saveFileName });
                                    if (!bSuccess)
                                    {
                                        Thread.Sleep(500);
                                    }
                                } while (!bSuccess);
                            }
                        }
                        Info($"{clientPath.ServerName}到{clientPath.Path}的{apiRes.Result.Count}个文件处理完成");
                    }
                    else
                    {
                        Info($"请求{clientPath.ServerName}失败：{apiRes.Message}");
                    }
                }
                Info("本次同步操作完成");
            });
            _isRunning = false;
        }

        private void Download(dynamic parameter)
        {
            TransFile serverFile = parameter.transFile;
            string pathName = parameter.ServerName;
            string saveFileName = parameter.saveFileName;

            using (var client = new HttpClient())
            {
                var content = new StringContent(new { FileName = serverFile.Path, PathName = pathName }.ToJson());
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var resp = client.PostAsync(SyncContext.Current.GetSyncConfig<ClientSyncConfig>().DownloadUrl, content).Result;
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    var stream = resp.Content.ReadAsStreamAsync().Result;
                    var serverMd5 = MD5Helper.Md5Stream(stream);
                    stream.Seek(0, SeekOrigin.Begin);
                    string localMd5;
                    bool bNewFile = true;
                    if (File.Exists(saveFileName))
                    {
                        localMd5 = MD5Helper.Md5File(saveFileName);
                        if (serverMd5 == localMd5)
                        {
                            bNewFile = false;
                            PathHelper.ChangeFileInfo(serverFile.Type, saveFileName, serverFile.CreatedTime, serverFile.ModifiedTime, serverFile.AccessedTime);
                        }
                        else
                        {
                            WriteToFile(saveFileName, stream, true);
                        }
                    }
                    else
                    {
                        WriteToFile(saveFileName, stream);
                    }
                    if (bNewFile && serverMd5 == (localMd5 = MD5Helper.Md5File(saveFileName)))
                    {
                        PathHelper.ChangeFileInfo(serverFile.Type, saveFileName, serverFile.CreatedTime, serverFile.ModifiedTime, serverFile.AccessedTime);
                        Info($"新下载的文件：{saveFileName}，{serverMd5},{localMd5}"); ;
                    }
                }
                else
                {
                    Info($"下载{serverFile.Path},{pathName}失败{resp.Content.ReadAsStringAsync().Result}");
                }
            }
        }
    }
}

